#include "_mysql.h"
#include <vector>
#include "_ccfree.h"
#include "rtdbFun.h"
#include <pthread.h>
#include <thread>
#include <queue>
#include <condition_variable>

pthread_mutex_t  dbmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

typedef struct s_table{
    int id;
    char date[21];
    char displayid[64];
    char itemid[64];
    char stageid[64];
    char pointid[64];
    char propname[64];
    char deviceid[64];
    int flag;
}s_table;

std::deque<s_table> vtable;

void getmysql()
{
    connection conn;

    if (conn.connecttodb("127.0.0.1,root,lilian,jinan,3306","utf8") != 0)
	{
		printf("connect database failed.\n%s\n",conn.m_cda.message);
	}

    sqlstatement stmt(&conn); 
    s_table stable;
    int iminid, imaxid;

    stmt.prepare("\
                    SELECT ID,date_format(UPDATE_TIME,'%%Y-%%m-%%d %%h:%%i:%%s'),DISPLAY_ID,ITEM_ID,STAGE_ID,POINT_ID,PROP_NAME,DEVICEID \
                    FROM `NewTable` where UPDATEFLAG=1");
    stmt.bindout(1, &stable.id);
    stmt.bindout(2, stable.date,20);
    stmt.bindout(3, stable.displayid,64);
    stmt.bindout(4, stable.itemid, 64);
    stmt.bindout(5, stable.stageid, 64);
    stmt.bindout(6, stable.pointid, 64);
    stmt.bindout(7, stable.propname, 64);
    stmt.bindout(8, stable.deviceid, 64);
    // stmt.bindout(9, &stable.flag);

    // while(1)
    {
        if(stmt.execute() != 0)
        {
            printf("stmt.excute() failedn.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); 
        }

        while(1)
        {
            memset(&stable, 0, sizeof(stable));

            if(stmt.next() != 0) break;

            // pthread_mutex_lock(&dbmutex);
            vtable.push_back(stable);
            // pthread_mutex_lock(&dbmutex);

            printf("id=%ld, date=%s, displayid=%s, itemid=%s, stageid=%s, pointid=%s, propname=%s deviceid=%s\n",\
                stable.id, stable.date, stable.displayid,stable.itemid,stable.itemid,stable.pointid,stable.propname,stable.deviceid);
        }

        printf("本次查询了table表%ld条记录。\n",stmt.m_cda.rpc);
        sleep(2);
    }

}


#include "fore_rtdb.h" 

void Createdb()
{
	EmptyAll(); 

	printf("CreateRtdb begin.....\n");
 
	CreateRTdb( "SYS_STRING_KEY_NAME",	SYS_STRING_KEY_NO, SYS_STRING_KEY_COUNT,sizeof(SYS_STRING_KEY));
	 
	CreateRTdb( "FORE_YC_POINT_RTDB_NAME",	FORE_YC_POINT_NO, FORE_YC_POINT_COUNT,sizeof(FORE_YC_POINT)); 
	 	
	printf("CreateRtdb end.....\n");
}


int qsort_yc_point( const void *a , const void *b )
{
	FORE_YC_POINT * p1 = (FORE_YC_POINT*)a;
	FORE_YC_POINT * p2 = (FORE_YC_POINT*)b; 
 
	if( strcmp( p1->dev_nodeID, p2->dev_nodeID ) > 0 ) 
		return 1;
	else if( strcmp( p1->dev_nodeID, p2->dev_nodeID ) < 0 ) 
		return -1;
	else 
	{
		if( strcmp( p1->name, p2->name ) > 0 ) 
			return 1;
		else if( strcmp( p1->name, p2->name) < 0 ) 
			return -1;
		else return 0;
	}
}
 
void printf_yc_rtdb( )
{
	printf("\n\n -----------------printf_yc_rtdb--------- \n\n");

	tHandle handle = OpenLib(FORE_YC_POINT_NO);
	if( !IsHandleValid(handle) ) {
		printf("FORE_YC_POINT_NO is InValid \n");
		// return ;
	}
	
	std::vector<FORE_YC_POINT>  aryYc; 

	FORE_YC_POINT yc_rec;
	bool ret = ReadFirst(handle, (char*)&yc_rec, sizeof(FORE_YC_POINT ));

	while(ret)
	{  
		aryYc.push_back(yc_rec);  
		ret = ReadNext(handle, (char*)&yc_rec, sizeof(FORE_YC_POINT ));
	}
	
	CloseLib( handle );
	
	if( aryYc.size() > 0 )
		qsort(aryYc.data(), aryYc.size(), sizeof(FORE_YC_POINT), qsort_yc_point );

	for( int i=0; i<aryYc.size(); i++ )
	{
		FORE_YC_POINT & yc_rec = aryYc[i];
		
		printf("key = %lld, dev_nodeID = %s, name = %s, time=%d, val = %0.3f, appName = %s coff = %f \n",  \
		yc_rec.KEY, yc_rec.dev_nodeID, yc_rec.name, yc_rec.LastUpdateTime, yc_rec.CurYcValue, yc_rec.appName, yc_rec.coff);
	}
	 
	printf(" \n \n\n  count = %d  \n", aryYc.size() );
}

bool put_to_rtdb()
{
    if ( OpenDbms() == false )
	{
		printf("open databases failed.\n");
	}
	else
	{
		printf("open databases success\n");
	}

	char  key[64] = {0};
	char  name[32] = {0};

	float coff;
	char  nodeId[64] = {0};
	char  meaName[64] = {0};
    //判断实时库是否被创建过
	if( !IsLibNoValid(SYS_STRING_KEY_NO) || !IsLibNoValid(FORE_YC_POINT_NO) )
	{
		Createdb();	
		SaveRtdb();		
		printf("Load rtdb rtdbms\n");
	}
	else {
		if( !LoadRtdb() ) 
		{
			printf(" Load rtdb rtdbms failed2! \n"); 
		}
		else
		{
			printf(" Load rtdb rtdbms sucess2! \n"); 
		} 
	}
    connection conn;

    if (conn.connecttodb("127.0.0.1,root,lilian,jinan,3306","utf8") != 0)
    {
        printf("connect database failed.\n%s\n",conn.m_cda.message);
    }

    sqlstatement stmt(&conn); 

	sleep(2);
	//插入记录（下面有savertdb 所以这里这调用一次就行，即第二次运行程序时，LoadRtdb函数会自动装载上次运行插入的记录，这里需要注意，通常这里插入记录就插入一次就行， ）

    FORE_YC_POINT   yc_rec;
    s_table dbre;

    while(1)
    {
        pthread_mutex_lock(&dbmutex);
		if(vtable.size() == 0 ) 
		{
			pthread_mutex_unlock(&dbmutex);
			sleep(2);
			continue;
		}
		else
		{
			dbre = vtable.front();
		}

        sprintf(meaName, "%s", dbre.propname );  //对应xml中的  PhV_phsA、PhV_phsB等
        sprintf(nodeId, "%s:%s", dbre.deviceid,dbre.pointid);
    
        strcpy(yc_rec.dev_nodeID, nodeId);
        strcpy(yc_rec.name, meaName);

        UpdateRec_stringkey_Ex(FORE_YC_POINT_NO, nodeId, (char *)&yc_rec, sizeof(FORE_YC_POINT));
        printf_yc_rtdb();
       
        stmt.prepare("\
                UPDATE NewTable set UPDATEFLAG = 0 where id = :1");
        stmt.bindin(1, &dbre.id);

        if(stmt.execute() != 0)
        {
            printf("stmt.excute() failedn.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message);
        }

        vtable.pop_front();
        pthread_mutex_unlock(&dbmutex);
    }

}


int main(int argc, char* argv[]) 
{
    thread getdb = thread(getmysql);
    thread putrtdb = thread(put_to_rtdb);

    // getmysql();

    getdb.join();
    putrtdb.join();

    return 0;
}